﻿#define _CRT_SECURE_NO_WARNINGS 1
//缺省参数
#include<iostream>
using namespace std;

//全缺省
//void func(int a = 10, int b = 20, int c = 30)
//{
//	cout << a << " ";
//	cout << b << " ";
//	cout << c << endl;
//	
//}
//
//int main()
//{
//	//全缺省传参只能从做往右给
//	func();
//	func(1);
//	func(1, 2);
//	func(1, 2, 3);
//	//func(1, , 3);//err 语法不支持这样写
//	//func(, ,3);//err 语法不支持这样写
//
//	return 0;
//}

//半缺省参数
//半缺省语法规定只能从右往左给缺省值
//void func(int a, int b = 20, int c = 30)
//{
//	cout << a << " ";
//	cout << b << " ";
//	cout << c << endl;
//
//}
//
//int main()
//{
//	//全缺省传参只能从做往右给
//	func(1,2);
//	func(1);
//	//func();//err 半缺省至少要给一个参数
//
//
//	return 0;
//}

//函数重载
//1.参数类型不同，可以重载
//int Add(int x, int y)
//{
//	return x + y;
//}
//
//double Add(double x, double y)
//{
//	return x + y;
//}
//
////2.参数个数不同，可以重载
//void func()
//{
//	cout << "void func()" << endl;
//}
//
//void func(int x)
//{
//	cout << "void func(int x)" << endl;
//}
//
////3.err 能构成重载但这里是有问题的
////但调用func()时编译器不知道调用哪个这是就会有歧义
////所以在实际中直接写void func(int x = 2)即可，因为它的功能也能用func()调用
//void func()
//{
//	cout << "void func()" << endl;
//}
//
//void func(int x = 2)
//{
//	cout << "void func(int x)" << endl;
//}
//
//
//int main()
//{
//	//int a = 10;
//	//int b = 20;
//	//double d1 = 3.3;
//	//double d2 = 5.5;
//
//	//cout << Add(a, b) << endl;
//	//cout << Add(d1, d2) << endl;
//
//	func();
//	func(1);
//
//	return 0;
//}

//引⽤的定义
//int main()
//{
//	int a = 0;
//	int b = a;//这是将a的值拷贝给b这个变量
//
//	int& c = a;//这是引用,相当于给起了一个别名
//
//	//a和b的地址是一样的，所以用a时是没有开额外空间的
//	cout << &a << endl;
//	cout << &c << endl;
//
//	return 0;
//}

//引⽤的特性
//int main()
//{
//	int a = 0;
//	//int& b;//err 特性1：引用必须初始化
//
//	//特性2：一个变量可以有多个引用
//	int& c = a;
//	int& d = a;
//
//	//特性3：一旦引用就不能引用其他实体
//	int& x = a;
//	int t = 10;
//	x = t;//这是赋值
//	//int& x = t;//err 这样就重定义了
//	//&x = t;//err &贴在变量前就是取地址，贴在类型后就是引用
//
//	return 0;
//}

//引⽤的使⽤

//指针的方式实现swap
int swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}

//引用的方式实现
//引用的功能1：作参数，改变形参影响实参
int swap(int& p1, int& p2)
{
	int tmp = p1;
	p1 = p2;
	p2 = tmp;
}

struct S
{
	int arr[100];
	int size;
};

//结构体传值传参
//void func(S s)	{}

//结构体引用
//void func(S& s) {}

//对结构体指针的引用
//引用功能2：对指针的引用
//void func(S*& s) {}

//传值返回
//int func(int* p)
//{
//	return p[5];
//}

//传引用返回
//int& func(int* p)
//{
//	return p[5];
//}
//
//int main()
//{
//	//int a = 10;
//	//int b = 20;
//
//	//swap(&a, &b);
//
//	//swap(a, b);
//
//	//S s;
//	//func(s);
//
//	//S* s;
//	//func(s);
//
//	int* p = (int*)malloc(sizeof(int) * 10);
//	if (p == NULL)
//		return -1;
//
//	for (int i = 0; i < 10; i++)
//	{
//		p[i] = i + 1;
//	}
//
//	//func(p) += 2;//传值返回，会临时生成一个临时变量，临时变量具有常性，无法修改
//	
//	func(p) += 2;//返回的空间是在堆栈上的并且是传引用返回，返回的是对应下标的引用(别名)
//
//	return 0;
//}

//传引用返回的误用
//这是一个错误的写法
int& func()
{
	int a = 10;

	return a;
}

int main()
{
	//a是func函数栈帧内创建的局部变量，出了作用域就销毁了
	//此时返回的值是一个不确定的值，取决于编译器会不会在函数栈帧销毁时将对应的空间改成随机值
	//int x = func();

	//这样就更危险了，返回的是一个栈内的局部变量空间的引用
	//此时再用y返回就等于非法访问这个空间了
	int& y = func();

	return 0;
}